package mylab.io.base.fsm;

import com.google.common.base.Preconditions;

import java.util.concurrent.atomic.AtomicReference;

import lombok.extern.slf4j.Slf4j;
import mylab.base.foundation.lang.Callback;
import mylab.io.base.FSM;

@Slf4j
public abstract class FsmContext implements FSM {

    protected String id;
    private final AtomicReference<DasState> stateRef = new AtomicReference<>(new DasShutdownState());

    @Override
    public String getId() {
        return id;
    }

    public DasState getDasState() {
        return stateRef.get();
    }

    @Override
    public void setDasState(DasState state) {
        Preconditions.checkNotNull(state, "state is null");
        log.info("### setDasState ### previous:{} current:{}", stateRef.get().getStatus(), state.getStatus());
        stateRef.set(state);
    }

    public void initialize(Callback<Void> callback) {
        try {
            getDasState().execute(this, DasAction.Initialize, callback);
        } catch (Exception e) {
            Callback.dealOnException(callback, e);
        }
    }

    public void start(Callback<Void> callback) {
        try {
            getDasState().execute(this, DasAction.Start, callback);
        } catch (Exception e) {
            Callback.dealOnException(callback, e);
        }
    }

    public void stop(Callback<Void> callback) {
        try {
            getDasState().execute(this, DasAction.Stop, callback);
        } catch (Exception e) {
            Callback.dealOnException(callback, e);
        }
    }

    public void dispose(Callback<Void> callback) {
        try {
            getDasState().execute(this, DasAction.Dispose, callback);
        } catch (Exception e) {
            Callback.dealOnException(callback, e);
        }
    }

    protected abstract void initializeFunc(Callback<Void> callback);

    protected abstract void startFunc(Callback<Void> callback);

    protected abstract void stopFunc(Callback<Void> callback);

    protected abstract void disposeFunc(Callback<Void> callback);

}
